package com.jlf.core.engine.server.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jlf.core.constant.DomainConstant;
import com.jlf.core.engine.domain.SchemaFieldDO;
import com.jlf.core.engine.domain.SchemaIndexDO;
import com.jlf.core.engine.entity.index.EditIndexWrapper;
import com.jlf.core.engine.persistence.SchemaIndexPersistence;
import com.jlf.core.engine.query.SchemaIndexQueryInput;
import com.jlf.core.engine.server.SchemaIndexServer;
import com.jlf.core.error.Errors;
import com.jlf.core.output.ListResultWrapper;
import com.jlf.core.output.ResultException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 模型领域的索引管理服务实现
 *
 * @author wujr
 * 2023/7/15
 * @version 1.0
 * 【变更历史】
 * [wujr 2023/7/15 1.0 新增]
 */
@Slf4j
@RequiredArgsConstructor
public class SchemaIndexServerImpl implements SchemaIndexServer {
    private final SchemaIndexPersistence schemaIndexPersistence;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SchemaIndexDO add(SchemaIndexDO record, List<SchemaFieldDO> schemaFields) throws Exception {
        // 检查columns是否都合法
        if (!checkColumns(record, schemaFields)){
            throw new ResultException(Errors.OBJECT_NOT_BELONG_TO, "字段不属于该模型领域");
        }
        schemaIndexPersistence.save(record);
        return record;
    }

    @Override
    public void edit(EditIndexWrapper wrapper) throws Exception {
        wrapper.getRecord().setId(wrapper.getOriginal().getId());
        if (!checkColumns(wrapper.getRecord(), wrapper.getSchemaFields())){
            throw new ResultException(Errors.OBJECT_NOT_BELONG_TO, "字段不属于该模型领域");
        }
        schemaIndexPersistence.updateById(wrapper.getRecord());
    }

    @Override
    public void delete(SchemaIndexDO record) {
        schemaIndexPersistence.removeById(record.getId());
    }

    @Override
    public ListResultWrapper<SchemaIndexDO> query(SchemaIndexQueryInput input, Integer pageNo, Integer pageSize) {
        QueryWrapper<SchemaIndexDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(!StringUtils.isBlank(input.getDomainCode()), SchemaIndexDO::getDomainCode, input.getDomainCode())
                .eq(input.getUniqueness() != null, SchemaIndexDO::getUniqueness, input.getUniqueness())
                .eq(input.getType() != null, SchemaIndexDO::getType, input.getType())
                .eq(input.getStatus() != null, SchemaIndexDO::getStatus, input.getStatus())
                .and(!StringUtils.isBlank(input.getKey()), w -> w.like(SchemaIndexDO::getName, input.getKey())
                        .or().like(SchemaIndexDO::getColumns, input.getKey()))
                .orderByAsc(SchemaIndexDO::getDomainCode)
                .orderByAsc(SchemaIndexDO::getPriority)
                .orderByAsc(SchemaIndexDO::getName);
        if (pageNo < 1 || pageSize < 1){
            // 不分页
            List<SchemaIndexDO> records = schemaIndexPersistence.list(wrapper);
            return new ListResultWrapper<>(records);
        }
        Page<SchemaIndexDO> page = new Page<>(pageNo, pageSize);
        Page<SchemaIndexDO> records = schemaIndexPersistence.page(page, wrapper);
        ListResultWrapper<SchemaIndexDO> output = new ListResultWrapper<>(records.getRecords());
        output.setTotal((int)records.getTotal());
        return output;
    }

    private boolean checkColumns(SchemaIndexDO record, List<SchemaFieldDO> schemaFields){
        String[] columns = StringUtils.split(record.getColumns());
        for (String column : columns){
            if (!checkColumn(column, schemaFields)){
                // 该字段不属于当前模型领域
                log.info("模型：{} 的索引，该索引中有不属于该模型的字段：{}", record.getDomainCode(), column);
                return false;
            }
        }
        return true;
    }

    private boolean checkColumn(String column, List<SchemaFieldDO> schemaFields){
        for (SchemaFieldDO schemaIndex : schemaFields){
            if (column.equals(schemaIndex.getJdbcFieldCode())){
                return true;
            }
        }
        // 检查公共字段
        return DomainConstant.isCommonField(column);
    }
}
